package com.bytecamp.testplatform.service.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.bytecamp.testplatform.mapper.ApiInfoMapper;
import com.bytecamp.testplatform.mapper.TestCaseMapper;
import com.bytecamp.testplatform.mapper.TestResultMapper;
import com.bytecamp.testplatform.model.ApiInfo;
import com.bytecamp.testplatform.model.TestCase;
import com.bytecamp.testplatform.model.TestResult;
import com.bytecamp.testplatform.service.TestResultService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Service
@RequiredArgsConstructor
@Slf4j
public class TestResultServiceImpl implements TestResultService {

    private final TestCaseMapper testCaseMapper;
    private final ApiInfoMapper apiInfoMapper;
    private final TestResultMapper testResultMapper;
    private final RestTemplate restTemplate; // 注入之前配置的RestTemplate

    // 执行单个用例（新增baseUrl参数）
    @Override
    public String executeAndSave(Long caseId, String baseUrl) {
        // 1. 查询用例和接口信息（不变）
        TestCase testCase = testCaseMapper.selectById(caseId);
        if (testCase == null) {
            return "用例不存在（caseId=" + caseId + "）";
        }
        ApiInfo apiInfo = apiInfoMapper.selectById(testCase.getApiId());
        if (apiInfo == null) {
            return "接口不存在（apiId=" + testCase.getApiId() + "）";
        }

        // 2. 直接使用前端传递的baseUrl（不再硬编码）
        String apiPath = apiInfo.getPath();
        String method = apiInfo.getMethod();

        // 3. 执行用例（传递baseUrl）
        TestResult result = executeSingleCase(testCase, apiPath, method, baseUrl);
        testResultMapper.insert(result);

        // 4. 返回结果（不变）
        return result.getIsPass() == 1 ?
                "用例执行成功（通过）" :
                "用例执行失败：" + result.getFailReason();
    }

    // 批量执行用例（新增baseUrl参数）
    @Override
    public String batchExecuteAndSave(Long apiId, String baseUrl) {
        // 逻辑类似，使用传递的baseUrl执行所有用例
        List<TestCase> testCases = testCaseMapper.selectByApiId(apiId);
        if (testCases.isEmpty()) {
            return "该接口无测试用例（apiId=" + apiId + "）";
        }
        ApiInfo apiInfo = apiInfoMapper.selectById(apiId);
        if (apiInfo == null) {
            return "接口不存在（apiId=" + apiId + "）";
        }
        String apiPath = apiInfo.getPath();
        String method = apiInfo.getMethod();

        List<TestResult> results = new ArrayList<>();
        int passCount = 0;

        /*
        同步等待要等待每一个请求响应, 才发起下一个请求
        使用异步回调函数写入数据库吞吐量更高
         */
        for (TestCase caseItem : testCases) {
            TestResult result = executeSingleCase(caseItem, apiPath, method, baseUrl);
            results.add(result);
            if (result.getIsPass() == 1) {
                passCount++;
            }
        }
        testResultMapper.batchInsert(results);
        return String.format("共执行%d个用例，通过%d个，失败%d个",
                testCases.size(), passCount, testCases.size() - passCount);
    }

    /**
     * 查询结果列表
     */
    @Override
    public List<TestResult> getResults(Long caseId, Long apiId) {
        if (caseId != null) {
            return testResultMapper.selectByCaseId(caseId);
        } else if (apiId != null) {
            return testResultMapper.selectByApiId(apiId);
        } else {
            return testResultMapper.selectAll();
        }
    }

    /**
     * 执行单个用例的具体逻辑（发送请求+验证结果）
     */
    private TestResult executeSingleCase(TestCase testCase, String apiPath, String method, String baseUrl) {
        TestResult result = new TestResult();
        result.setCaseId(testCase.getId());
        result.setExecuteTime(LocalDateTime.now());

        try {
            // 1. 解析用例的请求参数和预期结果
            String requestData = testCase.getRequestData(); // JSON字符串，如{"pageNum":1,"pageSize":10}
            String expectedResult = testCase.getExpectedResult(); // 如{"code":0,"msg":"成功"}

            // 2. 构建请求URL
            String requestUrl = baseUrl + apiPath;
            log.info("执行用例（caseId={}）：{} {}，参数：{}",
                    testCase.getId(), method, requestUrl, requestData);

            // 3. 构建请求头和请求体
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            HttpEntity<String> requestEntity = new HttpEntity<>(requestData, headers);

            // 4. 发送HTTP请求并记录耗时
            long startTime = System.currentTimeMillis();
            ResponseEntity<String> response = sendRequest(method, requestUrl, requestEntity);
            long endTime = System.currentTimeMillis();
            result.setDuration((int) (endTime - startTime)); // 毫秒

            // 5. 记录实际响应
            String actualResponse = response.getStatusCode().toString() + " " + response.getBody();
            result.setActualResult(actualResponse);
            log.info("用例（caseId={}）响应：{}，耗时：{}ms",
                    testCase.getId(), actualResponse, result.getDuration());

            // 6. 验证结果（对比预期和实际）
            boolean isPass = verifyResult(expectedResult, response.getBody());
            result.setIsPass(isPass ? 1 : 0);
            if (!isPass) {
                result.setFailReason("预期结果不匹配：预期=" + expectedResult + "，实际=" + response.getBody());
            }

        } catch (Exception e) {
            // 处理异常（如连接失败、超时等）
            result.setIsPass(0);
            result.setFailReason("执行异常：" + e.getMessage());
            log.error("用例（caseId={}）执行异常", testCase.getId(), e);
        }

        return result;
    }

    /**
     * 发送HTTP请求（适配不同方法）
     */
    private ResponseEntity<String> sendRequest(String method, String url, HttpEntity<String> requestEntity) {
        switch (method.toUpperCase()) {
            case "GET":
                // GET请求：参数需拼接在URL（简单处理，复杂参数需URL编码）
                String queryString = buildQueryString(requestEntity.getBody());
                return restTemplate.getForEntity(url + "?" + queryString, String.class);
            case "POST":
                return restTemplate.postForEntity(url, requestEntity, String.class);
            case "PUT":
                return restTemplate.exchange(url, HttpMethod.PUT, requestEntity, String.class);
            case "DELETE":
                return restTemplate.exchange(url, HttpMethod.DELETE, requestEntity, String.class);
            default:
                throw new RuntimeException("不支持的HTTP方法：" + method);
        }
    }

    /**
     * 验证实际响应是否符合预期（核心逻辑）
     */
    private boolean verifyResult(String expectedJson, String actualJson) {
        try {
            JSONObject expected = JSON.parseObject(expectedJson);
            JSONObject actual = JSON.parseObject(actualJson);

            // 至少验证code是否一致（可扩展其他关键字段）
            if (expected.containsKey("code") && actual.containsKey("code")) {
                return expected.getInteger("code").equals(actual.getInteger("code"));
            }
            // 若预期结果不含code，默认通过（或根据业务调整）
            return true;
        } catch (Exception e) {
            log.error("结果验证失败（预期={}, 实际={}）", expectedJson, actualJson, e);
            return false;
        }
    }

    /**
     * GET请求参数拼接（JSON转queryString）
     */
    private String buildQueryString(String requestData) {
        JSONObject json = JSON.parseObject(requestData);
        StringBuilder query = new StringBuilder();
        for (Map.Entry<String, Object> entry : json.entrySet()) {
            query.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
        }
        if (query.length() > 0) {
            query.setLength(query.length() - 1); // 移除最后一个&
        }
        return query.toString();
    }

    /**
     * 获取接口基础地址（实际项目中可从api_info表或配置文件读取）
     * 示例：从apiInfo的serviceName解析，或直接返回配置的默认地址
     */
    @Value("${api.base-url}")
    private String apiBaseUrl;

    // 替换getApiBaseUrl方法
    private String getApiBaseUrl(ApiInfo apiInfo) {
        return apiBaseUrl; // 直接返回配置的基础地址
    }
}